/**
 * Copyright (c) 2010 Axa Holding Belgium, SA. All rights reserved.
 * This software is the confidential and proprietary information of the AXA Group.
 */
package chabernac.tools;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

public class IOTools {
  private static Logger LOGGER = Logger.getLogger(IOTools.class); 
  
  public void writeObjectToFileAsXML(File aFile, Object anObject){
    //TODO implement writeObjectToFile
  }
  
  public Object loadObjectFromFileAsXML(File aFile){
    //TODO implement loadObjectFromFile
    return null;
  }
  
  public static void copyUntil(InputStream anInputStream, OutputStream anOutputStream, byte[] aSequence) throws IOException{
    LOGGER.debug( "Start copy untill");
    int theMatchingSequenceIndex = 0;
    int theCounter = 0;
    while(theMatchingSequenceIndex < aSequence.length){
      byte theByte = (byte)anInputStream.read();
      theCounter++;
      if(theByte == aSequence[theMatchingSequenceIndex]){
        theMatchingSequenceIndex++;
      } else {
        theMatchingSequenceIndex = 0;
      }

//      System.out.println("Byte[: "  + theCounter + "] " + (int)theByte);
      anOutputStream.write(theByte);
    }
    LOGGER.debug( "End copy untill");
  }
  
  public static byte[] readUntill(InputStream anInputStream, byte[] aSequence) throws IOException{
    byte[] theBytes = new byte[1024];
    int theIndex = 0;
    int theMatchingSequenceIndex = 0;
    while(theMatchingSequenceIndex < aSequence.length){
      byte theByte = (byte)anInputStream.read();
      if(theByte == aSequence[theMatchingSequenceIndex]){
        theMatchingSequenceIndex++;
      } else {
        theMatchingSequenceIndex = 0;
      }

      theBytes[theIndex++] = theByte;
      if(theIndex == theBytes.length){
        //grow the array
        byte[] theNewBytes = new byte[theBytes.length + 1024];
        System.arraycopy( theBytes, 0, theNewBytes, 0, theBytes.length);
        theBytes = theNewBytes;
      }
    }

    //trim the array
    byte[] theNewBytes = new byte[theIndex + 1];
    System.arraycopy( theBytes, 0, theNewBytes, 0, theNewBytes.length);
    return theNewBytes;
  }
  
  public static void copyStream(InputStream anInputStream, OutputStream anOutputStream) throws IOException{
    copyStream( anInputStream, anOutputStream, null );
  }
  
  public static void copyStreamUntilZeroes(InputStream anInputStream, OutputStream anOutputStream) throws IOException{
    int theZeroCounter = 0;
    int theByte;
    while( (theByte = anInputStream.read()) != -1 && theZeroCounter < 2){
      anOutputStream.write( theByte );
      if(theByte == 0) {
        theZeroCounter++;
      } else {
        theZeroCounter = 0;
      }
    }
  }
  
  public static void copyStreamSimple(InputStream anInputStream, OutputStream anOutputStream) throws IOException{
    int theByte;
    while((theByte = anInputStream.read()) != -1){
      anOutputStream.write( theByte );
    }
  }
  
  
  public static void copyStream(InputStream anInputStream, OutputStream anOutputStream, iTransferListener aListener) throws IOException{
    byte[] theBytes = new byte[1024];
    int length;
    long theBytesTransferred = 0;
    while((length = anInputStream.read(theBytes)) != -1){
      anOutputStream.write(theBytes, 0, length);
      if(aListener != null){
        theBytesTransferred += length;
        aListener.bytesTransfered( theBytesTransferred );
      }
    }
    anOutputStream.flush();
  }
  
  public static void copyStream(InputStream anInputStream, OutputStream anOutputStream, int aNumberOfBytes) throws IOException{
    byte[] theBytes = new byte[2048];
    int length;
    long theBytesTransferred = 0;
    long theBytesLeft = aNumberOfBytes - theBytesTransferred;
    int theBytesToRead = (int)Math.min( theBytes.length, theBytesLeft );
    
    while((length = anInputStream.read(theBytes, 0, theBytesToRead)) != -1 && theBytesToRead > 0){
      anOutputStream.write(theBytes, 0, length);
      theBytesTransferred += length;
      
      theBytesLeft = aNumberOfBytes - theBytesTransferred;
      theBytesToRead = (int)Math.min( theBytes.length, theBytesLeft );
    }
    anOutputStream.flush();
  }
  
  public static void copyLines(BufferedReader aReader, PrintWriter aWriter) throws IOException{
    String theLine = null;
    while((theLine = aReader.readLine()) != null){
      aWriter.println( theLine );
    }
  }
  
  public static List<String> loadFileAsList(File aFile){
    List<String> theList = new ArrayList< String >();
    if(!aFile.exists()) return theList;
    
    BufferedReader theReader = null;
    try{
      theReader = new BufferedReader(new FileReader(aFile));
      String theLine = null;
      while((theLine = theReader.readLine()) != null){
        theList.add(theLine);
      }
    } catch ( FileNotFoundException e ) {
      LOGGER.error("Could not open fixed ip list file", e);
    } catch ( IOException e ) {
      LOGGER.error("Could not read fixed ip list file", e);
    } finally {
      if(theReader != null){
        try {
          theReader.close();
        } catch ( IOException e ) {
          LOGGER.error("Could not close fixed ip list file", e);
        }
      }
    }
    return theList;
  }
}
